﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Web;
using System.Windows.Forms;
using TrainTicketsAuto.Helper;
using TrainTicketsAuto.Ocrlib;

namespace TrainTicketsAuto
{
    public partial class MainForm : Form
    {
        #region Class Properties

        private bool isPause = false;
        private bool isLogined = false;
        private Dictionary<string, string> dicThrainList;
        private List<TrainInfo> _newestThrainInfo;
        private List<OrderInfo> _allCheckedUserTicketInfos;
        private List<TrainDetailInfo> _trainDetailInfos;
        private List<Thread> _threadList = new List<Thread>();

        #region Control value(for threading visit)

        #endregion

        public static readonly MainForm MainFormInstance = new MainForm();

        #endregion

        #region Initialization

        private MainForm()
        {
            InitializeComponent();
            InitControls();
        }

        private void InitControls()
        {
            InitTimeCombo();
            InitTicketClassCombo();
            InitSeatTypeCombo();
        }

        private void InitAutoLoad()
        {
            InitAutoLoadOrderInfo();
            InitAutoLoadThrainInfo();
        }

        #endregion

        #region Initial Operations

        private void InitTimeCombo()
        {
            BindingSource bs = new BindingSource();
            bs.DataSource = Predefined.TrainTime;
            StartTime.DataSource = bs;
            StartTime.DisplayMember = "Key";
            StartTime.ValueMember = "Value";
        }

        private void InitTicketClassCombo()
        {
            BindingSource bs = new BindingSource();
            bs.DataSource = Predefined.TicketClass;
            TicketClass.DataSource = bs;
            TicketClass.DisplayMember = "Key";
            TicketClass.ValueMember = "Value";
        }

        private void InitSeatTypeCombo()
        {
            BindingSource bs = new BindingSource();
            bs.DataSource = Predefined.SeatType;
            SeatType.DataSource = bs;
            SeatType.DisplayMember = "Key";
            SeatType.ValueMember = "Value";
        }

        #endregion

        #region Initial auto loads operations

        private void InitAutoLoadOrderInfo()
        {
            List<OrderInfo> orderInfos = LoadOrderInfoFromXml();
            if (orderInfos != null)
            {
                for (int i = 0; i < orderInfos.Count; i++)
                {
                    BookingInformation.Rows.Add();
                    BookingInformation.Rows[i].Cells["IsChecked"].Value = orderInfos[i].IsChecked;
                    BookingInformation.Rows[i].Cells["TrainCode"].Value = orderInfos[i].TrainCode;
                    BookingInformation.Rows[i].Cells["TicketClass"].Value = orderInfos[i].TicketClass;
                    BookingInformation.Rows[i].Cells["SeatType"].Value = orderInfos[i].SeatType;
                    BookingInformation.Rows[i].Cells["IdCard"].Value = orderInfos[i].IdCard;
                    BookingInformation.Rows[i].Cells["PeopleName"].Value = orderInfos[i].Name;
                    BookingInformation.Rows[i].Cells["Tel"].Value = orderInfos[i].Tel;
                }
            }
        }

        private void InitAutoLoadThrainInfo()
        {
            List<TrainInfo> trainInfo = LoadTrainInfoFromXml();
            if (trainInfo != null)
            {
                foreach (var info in trainInfo)
                {
                    StartStation.Text = info.FromStation;
                    EndStation.Text = info.ToStation;
                    StartDate.Value = ConvertHelper.ConvertDateTime(info.DepartureDate);
                    if (info.DepartureTime != "")
                    {
                        StartTime.SelectedValue = info.DepartureTime;
                    }
                }
            }
        }

        #endregion

        #region EventHandler

        private void StartBt_Click(object sender, EventArgs e)
        {
            if (CheckInput())
            {
                if (_threadList.Count == 0)
                {
                    // work
                    StartBt.Text = InfoResource.StartBtStatus2;
                    Thread threadStart = new Thread(new ThreadStart(Start));
                    threadStart.Name = "ThreadStart";
                    threadStart.IsBackground = true;
                    threadStart.Start();

                    _threadList.Add(threadStart);
                }
                else
                {
                    if (!isPause)
                    {
                        ChangeAllThreadState("suspend");
                        StartBt.Text = InfoResource.StartBtStatus3;
                        isPause = true;
                    }
                    else
                    {
                        ChangeAllThreadState("resume");
                        StartBt.Text = InfoResource.StartBtStatus2;
                        isPause = false;
                    }
                }
            }
        }

        private void StopBt_Click(object sender, EventArgs e)
        {
            try
            {
                ChangeAllThreadState("abort");
                StartBt.Text = InfoResource.StartBtStatus1;
                isPause = false;
            }
            catch (Exception ex)
            {
            }

        }

        private void PopupBt_Click(object sender, EventArgs e)
        {
            string cookieValue;
            foreach (Cookie cookie in HttpHelper.CookieContainers.GetCookies(new Uri(InfoResource.LoginActionUrl)))
            {
                if (cookie.Name == "JSESSIONID")
                {
                    cookieValue = cookie.Value + ";Path=/otsweb;expires=Sun,22-Feb-2099 00:00:00 GMT";
                }
                else
                {
                    cookieValue = cookie.Value + ";path=/;expires=Sun,22-Feb-2099 00:00:00 GMT";
                }
                if (!API.InternetSetCookie(InfoResource.LoginUrl, cookie.Name, cookieValue))
                {
                }
            }
            Process.Start("IExplore.exe", InfoResource.LoginUrl);
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            InitControls();
            InitAutoLoad();
            Control.CheckForIllegalCrossThreadCalls = false;
            GetCode();
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            SaveOrderInfoToXml();
            SaveTrainInfoToXml();
        }

        #endregion

        #region Process

        /// <summary>
        /// process start
        /// </summary>
        private void Start()
        {
            //
            while (true)
            {
                if (isLogined)
                {
                    Common.WriteOutPutResult(InfoResource.Booking);
                    Book();
                    _allCheckedUserTicketInfos = GetAllCheckedOrderInfo();
                }
                else
                {
                    Login();
                    dicThrainList = Common.GetThrainList();
                }

                Thread.Sleep(Convert.ToInt32(TimeInterval.Text)*1000);
            }
        }

        /// <summary>
        /// log in
        /// </summary>
        private void Login()
        {
            Common.WriteOutPutResult(InfoResource.Loging);

            for (int i = 0; i < 10000; i++)
            {
                try
                {
                    string afterLogin = LoginRequest();

                    if (afterLogin.Contains(InfoResource.LoginReturnVeriText1))
                    {
                        Common.WriteOutPutResult(InfoResource.LoginError1);
                        break;
                    }
                    else if (afterLogin.Contains(InfoResource.LoginReturnVeriText2))
                    {
                        Common.WriteOutPutResult(InfoResource.LoginSuccess);
                        isLogined = true;
                        break;
                    }
                    else if (afterLogin.Contains(InfoResource.LoginReturnVeriText3))
                    {
                        Common.WriteOutPutResult(InfoResource.LoginError3);
                        break;
                    }
                    else if (afterLogin.Contains(InfoResource.LoginReturnVeriText4))
                    {
                        Common.WriteOutPutResult(InfoResource.LoginError4);
                        GetCode();
                    }
                    else if (afterLogin.Contains(InfoResource.LoginReturnVeriText5))
                    {
                        Common.WriteOutPutResult(string.Format(InfoResource.LoginError5, i));
                        GetCode();
                    }
                    else
                    {
                        Common.WriteOutPutResult(string.Format(InfoResource.LoginError6, i));
                        GetCode();
                    }
                }
                catch
                {
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        private void Book()
        {

            List<OrderInfo> allCheckedOrderInfo = GetAllCheckedOrderInfo();
            List<TrainInfo> trainInfo = GetTrainInfo();
            string thrainQuery = QueryLeftTicket();
            foreach (var orderInfo in allCheckedOrderInfo)
            {
                BookTrain(orderInfo, trainInfo[0]);
            }

        }

        #endregion

        #region Httprequest or Response

        /// <summary>
        /// Get login request
        /// </summary>
        private string LoginRequest()
        {
            string loginUrl = InfoResource.LoginActionUrl;
            string userName = this.UserName.Text.Trim();
            string password = this.Password.Text.Trim();
            string code = this.Code.Text.Trim();
            // Get random number
            string randomUrl = InfoResource.loginAysnSuggest;
            string afterRandom = HttpHelper.GetResponse(randomUrl, "POST", string.Empty);
            string[] randoms = afterRandom.Split('"');
            string random = randoms[3];

            string data = "loginRand=" + random + "&refundLogin=N&refundFlag=Y&loginUser.user_name=" + userName +
                          "&nameErrorFocus=&user.password=" + password + "&passwordErrorFocus=&randCode=" + code +
                          "&randErrorFocus=";

            HttpWebRequest request = (HttpWebRequest) WebRequest.Create(loginUrl);
            request.ContentType = "application/x-www-form-urlencoded";
            request.Referer = InfoResource.LoginReferUrl;
            request.Accept = "text/html, application/xhtml+xml, */*";
            request.Headers["Cache-Control"] = "no-cache";

            return HttpHelper.GetResponse(request, loginUrl, "POST", data);
        }

        /// <summary>
        /// return thrain list based on user input
        /// </summary>
        /// <returns></returns>
        private string QueryLeftTicket()
        {
            string afterQuery = "";
            try
            {
                //query by StartDate,StartStation,EndStation,StartTime
                string QueryUrl =
                    string.Format(InfoResource.QuerySingleUrl,
                                  StartDate.Value.ToString("yyyy-MM-dd"),
                                  dicThrainList[StartStation.Text.Trim()],
                                  dicThrainList[EndStation.Text.Trim()],
                                  StartTime.SelectedValue);
                HttpWebRequest request = (HttpWebRequest) WebRequest.Create(QueryUrl);
                request.ContentType = "application/x-www-form-urlencoded";
                request.Referer = InfoResource.QuerySingleReferUrl;
                request.Accept = "text/html, application/xhtml+xml, */*";
                request.Headers["Cache-Control"] = "no-cache";

                afterQuery = HttpHelper.GetResponse(request, QueryUrl, "Get", "");
            }
            catch (Exception)
            {
                Common.WriteOutPutResult(InfoResource.QueryError1);
            }

            _trainDetailInfos=new List<TrainDetailInfo>();
            Match match = new Regex( @"</span>,.*?<a.*?(onclick=javascript:getSelected\('(.*?)'\))?>.*?</a>").Match(afterQuery);
            while (match.Success)
            {
                if (match.Groups[2].Value != "")
                {
                    _trainDetailInfos.Add(GetTrainDetailInfo(match.Groups[2].Value));

                }
                match = match.NextMatch();  
            }
    
            return afterQuery;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        private string BookTrain(OrderInfo orderInfo, TrainInfo trainInfo)
        {
            string afterQuery = "";
            TrainDetailInfo trainDetailInfo = null;
            foreach (var info in _trainDetailInfos)
            {
                if (info.StationTrainCode == orderInfo.TrainCode)
                {
                    trainDetailInfo = info;
                    break;
                }
            }

            if (trainDetailInfo != null)
            {
                string bSookUrl = InfoResource.SubmutOrderRequestUrl;
                string data =
                string.Format(InfoResource.SubmutOrderRequestData,
                              trainDetailInfo.StationTrainCode, // 车次
                              trainInfo.DepartureDate, // 时间
                              "",
                              trainDetailInfo.FromStationTelecode, // 起始站代码
                              trainDetailInfo.ToSationTelecode, // 到达站代码
                              "00", // 非学生票
                              HttpUtility.UrlEncode(trainDetailInfo.FromStationName, System.Text.Encoding.GetEncoding("UTF-8")), // 起始站名称
                              HttpUtility.UrlEncode(trainDetailInfo.ToSationName, System.Text.Encoding.GetEncoding("UTF-8")), // 到达站名称
                              trainInfo.DepartureDate, // 时间
                              trainInfo.DepartureTime, // 00:00--24:00
                              "1",
                              "QB", // 全部 代表所有列车类型
                              HttpUtility.UrlEncode("QB#D#Z#T#K#QT#", System.Text.Encoding.GetEncoding("UTF-8")), // QB#D#Z#T#K#QT# 代表所有列车类型
                              trainInfo.DepartureTime, // 00:00--24:00  出发时间
                              HttpUtility.UrlEncode(trainDetailInfo.LiShi, System.Text.Encoding.GetEncoding("UTF-8")), // 总花费时间
                              HttpUtility.UrlEncode(trainDetailInfo.TrainStartTime, System.Text.Encoding.GetEncoding("UTF-8")), // 发车时间
                              trainDetailInfo.Trainno4, // 嵌套车次
                              HttpUtility.UrlEncode(trainDetailInfo.ArriveTime, System.Text.Encoding.GetEncoding("UTF-8")), // 发车时间
                              HttpUtility.UrlEncode(trainDetailInfo.FromStationName, System.Text.Encoding.GetEncoding("UTF-8")), // 
                              HttpUtility.UrlEncode(trainDetailInfo.ToSationName, System.Text.Encoding.GetEncoding("UTF-8")), // 
                              trainDetailInfo.FromStationNo, // 出发站在该线路的坐标 01开始
                              trainDetailInfo.ToStationNo, // 到达站在该线路的坐标
                              trainDetailInfo.YPInfoDetail, // 
                              trainDetailInfo.MMStr, // 
                              trainDetailInfo.locationCode //
                    );
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(bSookUrl);
                request.ContentType = "application/x-www-form-urlencoded";
                request.Referer = InfoResource.QuerySingleReferUrl;
                request.Accept = "text/html, application/xhtml+xml, */*";
                request.Headers["Cache-Control"] = "no-cache";

                afterQuery = HttpHelper.GetResponse(request, bSookUrl, "Get", "");
            }

            return afterQuery;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="orderInfo"></param>
        /// <returns></returns>
        private string SubmitOrder(OrderInfo orderInfo, TrainInfo trainInfo)
        {

            return null;
        }

        private string ConfirmOrder(OrderInfo orderInfo, TrainInfo trainInfo)
        {

            return null;
        }

        /// <summary>
        /// Get 12306 code
        /// </summary>
        private void GetCode()
        {
            //Common.WriteOutPutResult(InfoResource.GetCodeTip1);
            //string url = InfoResource.PassCodeAction;

            //Stream stream = null;
            //for (int i = 0; i < 10000; i++)
            //{
            //    stream = HttpHelper.GetResponseImage(url);
            //    if (stream != null)
            //    {
            //        break;
            //    }
            //    else
            //    {
            //        Common.WriteOutPutResult(InfoResource.GetCodeTip2);
            //    }
            //}

            //Bitmap image = new Bitmap(Image.FromStream(stream));
            //AssignCodePic(image);
            //Common.WriteOutPutResult(InfoResource.GetCodeTip3);
            //AssignCode(PicProcess.GetTextFromPic(image));


            //using (Bitmap image1 = MainForm.ChangeGray(image))
            //{
            //    image.Dispose();
            //    image = null;
            //    image1.Save("D:\\1.jpg", ImageFormat.Jpeg);
            //}

        }

        #endregion

        #region Common code

        /// <summary>
        /// check user input
        /// </summary>
        /// <returns></returns>
        private bool CheckInput()
        {
            // Verify login field
            if (this.UserName.Text.Length < 2)
            {
                MessageBox.Show(InfoResource.LoginVeri1);
                return false;
            }
            if (this.Password.Text.Length < 4)
            {
                MessageBox.Show(InfoResource.LoginVeri2);
                return false;
            }
            return true;
        }

        private void ChangeAllThreadState(string threadState)
        {
            foreach (Thread t in _threadList)
            {
                try
                {
                    switch (threadState)
                    {
                        case "abort":
                            if (t.ThreadState.ToString().Contains(System.Threading.ThreadState.Suspended.ToString()))
                            {
                                t.Resume();
                            }
                            t.Abort();
                            _threadList = new List<Thread>();
                            break;
                        case "suspend":
                            if (!t.ThreadState.ToString().Contains(System.Threading.ThreadState.Suspended.ToString()))
                            {
                                t.Suspend();
                            }
                            break;
                        case "resume":
                            if (t.ThreadState.ToString().Contains(System.Threading.ThreadState.Suspended.ToString()))
                            {
                                t.Resume();
                            }
                            break;
                    }
                }
                catch (Exception ex)
                {
                    Common.WriteOutPutResult(ex.Message);
                }
            }
        }

        /// <summary>
        /// get all checked user ticket information
        /// </summary>
        /// <returns>List<OrderInfo></returns>
        private List<OrderInfo> GetAllCheckedOrderInfo()
        {
            List<OrderInfo> allCheckedOrderInfo = new List<OrderInfo>();
            try
            {
                allCheckedOrderInfo.AddRange(from orderInfo in GetAllOrderInfo()
                                             where orderInfo.IsChecked
                                             select new OrderInfo()
                                                 {
                                                     IsChecked = orderInfo.IsChecked,
                                                     TrainCode = orderInfo.TrainCode,
                                                     TicketClass = orderInfo.TicketClass,
                                                     SeatType = orderInfo.SeatType,
                                                     Name = orderInfo.Name,
                                                     IdCard = orderInfo.IdCard,
                                                     Tel = orderInfo.Tel
                                                 });
            }
            catch (Exception ex)
            {
                Common.WriteOutPutResult(InfoResource.NoChoiseUserInfo);
            }



            return allCheckedOrderInfo;
        }

        /// <summary>
        /// get all user ticket information
        /// </summary>
        /// <returns>List<UserTicketInfo></returns>
        private List<OrderInfo> GetAllOrderInfo()
        {
            List<OrderInfo> allOrderInfo = new List<OrderInfo>();
            try
            {
                allOrderInfo.AddRange(from DataGridViewRow dr in BookingInformation.Rows
                                      where ConvertHelper.ConvertString(dr.Cells["TicketClass"].Value) != ""
                                      orderby dr.Cells["IsChecked"].Value descending
                                      select new OrderInfo()
                                          {
                                              IsChecked = ConvertHelper.ConvertBoolean(dr.Cells["IsChecked"].Value),
                                              TrainCode = ConvertHelper.ConvertString(dr.Cells["TrainCode"].Value),
                                              TicketClass =ConvertHelper.ConvertString(dr.Cells["TicketClass"].Value).Trim(),
                                              SeatType = ConvertHelper.ConvertString(dr.Cells["SeatType"].Value).Trim(),
                                              Name = ConvertHelper.ConvertString(dr.Cells["PeopleName"].Value).Trim(),
                                              IdCard = ConvertHelper.ConvertString(dr.Cells["IDCard"].Value).Trim(),
                                              Tel = ConvertHelper.ConvertString(dr.Cells["Tel"].Value).Trim()
                                          });
            }
            catch (Exception ex)
            {
                Common.WriteOutPutResult(InfoResource.NoChoiseUserInfo);
            }

            return allOrderInfo;
        }

        /// <summary>
        /// get all user ticket information
        /// </summary>
        /// <returns>List<UserTicketInfo></returns>
        private List<TrainInfo> GetTrainInfo()
        {
            List<TrainInfo> trainInfo = new List<TrainInfo>();
            try
            {
                trainInfo.Add(new TrainInfo()
                    {
                        FromStation = StartStation.Text.Trim(),
                        ToStation = EndStation.Text.Trim(),
                        DepartureDate = StartDate.Value.ToString("yyyy-MM-dd").Trim(),
                        DepartureTime = ConvertHelper.ConvertString(StartTime.SelectedValue).Trim()
                    });
            }
            catch (Exception ex)
            {
                Common.WriteOutPutResult(InfoResource.GetTrainInfoError);
            }

            return trainInfo;
        }

        /// <summary>
        /// Save order information to xml into application startup folder
        /// </summary>
        private void SaveOrderInfoToXml()
        {
            List<OrderInfo> allUserTicketInfos = GetAllOrderInfo();
            if (allUserTicketInfos.Count > 0)
            {
                string xml = ConvertHelper.ObjListToXml(allUserTicketInfos, InfoResource.XmlHeadTagName1);
                ConvertHelper.CDataToXmlFile(xml, Application.StartupPath + InfoResource.XmlFolderPath1,
                                             InfoResource.XmlName1);
            }
        }

        /// <summary>
        /// Save train information to xml into application startup folder
        /// </summary>
        private void SaveTrainInfoToXml()
        {
            List<TrainInfo> trainInfo = GetTrainInfo();

            if (trainInfo.Count > 0)
            {
                string xml = ConvertHelper.ObjListToXml(trainInfo, InfoResource.XmlHeadTagName2);
                ConvertHelper.CDataToXmlFile(xml, Application.StartupPath + InfoResource.XmlFolderPath2,
                                             InfoResource.XmlName2);
            }
        }

        /// <summary>
        /// load order informatin from xml
        /// </summary>
        /// <returns>List<OrderInfo> </returns>
        private List<OrderInfo> LoadOrderInfoFromXml()
        {
            List<OrderInfo> orderInfo = new List<OrderInfo>();
            try
            {
                List<string> orderInfoStrs =
                    ConvertHelper.ReadAllFilesFromPath(Application.StartupPath + InfoResource.XmlFolderPath1, ".xml");
                foreach (var orderInfoStr in orderInfoStrs)
                {
                    orderInfo.AddRange(ConvertHelper.LinqXmlToObjList<OrderInfo>(orderInfoStr,
                                                                                 InfoResource.XmlHeadTagName1));
                }
            }
            catch (Exception ex)
            {
            }

            return orderInfo;
        }

        /// <summary>
        /// load train informatin from xml
        /// </summary>
        /// <returns>List<TrainInfo> </returns>
        private List<TrainInfo> LoadTrainInfoFromXml()
        {
            List<TrainInfo> trainInfo = new List<TrainInfo>();
            try
            {
                List<string> orderInfoStrs =
                    ConvertHelper.ReadAllFilesFromPath(Application.StartupPath + InfoResource.XmlFolderPath2, ".xml");
                foreach (var orderInfoStr in orderInfoStrs)
                {
                    trainInfo.AddRange(ConvertHelper.LinqXmlToObjList<TrainInfo>(orderInfoStr,
                                                                                 InfoResource.XmlHeadTagName2));
                }
            }
            catch (Exception ex)
            {
            }

            return trainInfo;
        }

        //private bool CheckTrainQuery(out )
        //{
            
        //}

        /// <summary>
        /// Sample:G7222#01:59#06:34#55000G722230#SHH#INH#08:33#上海#全椒#01#05#O*****06289*****0028O*****3000M*****0174#43EB7C39EFB4AADA79D39199B1FF3E68D1902561529FF133A6F5AE31#H3
        /// </summary>
        /// <param name="info"></param>
        /// <returns></returns>
        private TrainDetailInfo GetTrainDetailInfo(string info)
        {
            string[] infoDetail = info.Split('#');
            TrainDetailInfo trainDetailInfo = new TrainDetailInfo()
                {
                    StationTrainCode = infoDetail[0],
                    FromStationTelecode = infoDetail[4],
                    ToSationTelecode = infoDetail[5],
                    FromStationName = infoDetail[7],
                    ToSationName = infoDetail[8],
                    LiShi = infoDetail[1],
                    TrainStartTime=infoDetail[2],
                    Trainno4 = infoDetail[3],
                    ArriveTime = infoDetail[6],
                    FromStationNo = infoDetail[9],
                    ToStationNo = infoDetail[10],
                    YPInfoDetail = infoDetail[11],
                    MMStr = infoDetail[12],
                    locationCode = infoDetail[13]
                };
            return trainDetailInfo;
        }

        #endregion

        #region Controls Operations

        public void AssignCode(string text)
        {
            if (Code.InvokeRequired)
            {
                this.CodePictureBox.Invoke(new MethodInvoker(delegate
                    {
                        Code.Text = text.ToString();
                    }));
            }
            else
            {
                Code.Text = text.ToString();
            }
        }

        public void AssignCodePic(Image image)
        {
            if (CodePictureBox.InvokeRequired)
            {
                this.CodePictureBox.Invoke(new MethodInvoker(delegate
                    {
                        CodePictureBox.Image = image;
                    }));
            }
            else
            {
                CodePictureBox.Image = image;
            }
        }

        public void AssignOutputInformation(string text)
        {
            if (OutputInformation.InvokeRequired)
            {
                this.OutputInformation.Invoke(new MethodInvoker(delegate
                    {
                        OutputInformation.AppendText(text + "\r\n");
                    }));
            }
            else
            {
                OutputInformation.AppendText(text + "\r\n");
            }
        }

        #endregion



        public static Bitmap ChangeGray(Bitmap b)
        {
            BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite,
                PixelFormat.Format24bppRgb);
            int stride = bmData.Stride;         // 扫描的宽度

            unsafe
            {
                byte* p = (byte*)bmData.Scan0.ToPointer(); // 获取图像首地址
                int nOffset = stride - b.Width * 3;        // 实际宽度与系统宽度的距离
                byte red, green, blue;
                for (int y = 0; y < b.Height; ++y)
                {
                    for (int x = 0; x < b.Width; ++x)
                    {
                        blue = p[0];
                        green = p[1];
                        red = p[2];

                        p[0] = p[1] = p[2] = (byte)(.299 * red + .587 * green + .114 * blue);  // 转换公式
                        p += 3;      // 跳过3个字节处理下个像素点
                    }
                    p += nOffset;    // 加上间隔
                }
            }
            b.UnlockBits(bmData);   // 解锁
            return b;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            new WebClientTmall("http://detail.tmall.com/item.htm?id=7968792181&areaId=&user_id=552515164&is_b=1&cat_id=50025137&q=&rn=f6854d7c819415477ce6a22ea52c6a74");
        }

    }
}